/**
 * 
 */
package br.embedded.socialapp.business;

import org.opensocial.Client;
import org.opensocial.Request;
import org.opensocial.RequestException;
import org.opensocial.Response;
import org.opensocial.services.PeopleService;
import org.opensocial.models.Person;

import br.embedded.socialapp.domain.Address;
import br.embedded.socialapp.domain.BodyType;
import br.embedded.socialapp.domain.FriendshipInfo;
import br.embedded.socialapp.domain.Url;
import br.embedded.socialapp.domain.PersonName;
import br.embedded.socialapp.domain.User;
import br.embedded.socialapp.domain.Usuario;

import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Date;

/**
 * @author daniel
 *
 */
public class SocialNetworkHandler
{
	private Client socialClient;
	private static final String[] parameters = { "@all" };
	
	public SocialNetworkHandler(String providerName)
	{
		this.socialClient = OpenSocialClientFactory.getInstance(providerName);
	}
	
	public User fetchPerson(String socialNetworkId)
	{
		User user = null;
		
		try 
		{
			Request request = PeopleService.getUser(socialNetworkId);
			request.setFieldsParameter(parameters);
			Response response = socialClient.send(request);
			Person person = response.getEntry();
			user = parseToUser(person);
			
		} catch (RequestException e) {
			//e.printStackTrace();
		} catch (IOException e) {
			//e.printStackTrace();
		}
		return user;
	}
	
	private User parseToUser(Person person) {
		User user = new User();
		
		
		int index = person.getId().lastIndexOf(".");	
		String id =	(index == -1) ? person.getId() : person.getId().substring(index + 1, person.getId().length());
		user.setId(id);
		
		List<Usuario> list = UserManager.getInstance().getUserById("'" + id + "'");
		
		if (list.size() > 0)
			user.setLogin(list.get(0).getLogin());
		
		if (person.hasField("aboutMe"))
			user.setAboutMe(person.getFieldAsString("aboutMe"));
		if (person.hasField("fashion"))
			user.setFashion(person.getFieldAsString("fashion"));
		if (person.hasField("livingArrangement"))
			user.setLivingArrangement(person.getFieldAsString("livingArrangement"));
		if (person.hasField("romance"))
			user.setRomance(person.getFieldAsString("romance"));
		if (person.hasField("age"))
			user.setAge(Integer.parseInt(person.getFieldAsString("age")));
		if (person.hasField("ethnicity"))
			user.setEthnicity(person.getFieldAsString("ethnicity"));
		if (person.hasField("children"))
			user.setChildren(person.getFieldAsString("children"));
		if (person.hasField("hasApp"))
			user.setHasApp(Boolean.valueOf(person.getFieldAsString("hasApp")));
		
		if (person.hasField("dateOfBirth"))
		{
			DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
			try {
				Date data = dateFormat.parse(person.getFieldAsString("dateOfBirth"));
				user.setDateOfBirth(data.toString());
			} catch (ParseException e) {
				e.printStackTrace();
			}
		}
		if (person.hasField("relationshipStatus"))
			user.setRelationshipStatus(person.getFieldAsString("relationshipStatus"));
		if (person.hasField("religion"))
			user.setReligion(person.getFieldAsString("religion"));
		if (person.hasField("sexualOrientation"))
			user.setSexualOrientation(person.getFieldAsString("sexualOrientation"));
		if (person.hasField("status"))
			user.setStatus(person.getFieldAsString("status"));
		if (person.hasField("thumbnailUrl"))
			user.setThumbnailUrl(person.getFieldAsString("thumbnailUrl"));
		if (person.hasField("profileUrl"))
			user.setProfileUrl(person.getFieldAsString("profileUrl"));
		if (person.hasField("nickname"))
			user.setNickname(person.getFieldAsString("nickname"));
		if (person.hasField("humor"))
			user.setHumor(person.getFieldAsString("humor"));
		
		if (person.hasField("smoker"))
			user.setSmoker(extractFromMap(person.getFieldAsMap("smoker"), "displayValue"));
		if (person.hasField("networkPresence"))
			user.setNetworkPresence(extractFromMap(person.getFieldAsMap("networkPresence"), "value"));
		if (person.hasField("drinker"))
			user.setDrinker(extractFromMap(person.getFieldAsMap("drinker"), "displayValue"));
		if (person.hasField("gender"))
			user.setGender(person.getFieldAsString("gender"));
		
		if (person.hasField("movies"))
			user.setMovies(person.getFieldAsList("movies"));
		if (person.hasField("music"))
			user.setMusic(person.getFieldAsList("music"));
		if (person.hasField("interests"))
			user.setInterests(person.getFieldAsList("interests"));
		if (person.hasField("books"))
			user.setBooks(person.getFieldAsList("books"));
		if (person.hasField("heroes"))
			user.setHeroes(person.getFieldAsList("heroes"));
		if (person.hasField("tvShows"))
			user.setTvShows(person.getFieldAsList("tvShows"));
		if (person.hasField("sports"))
			user.setSports(person.getFieldAsList("sports"));
		if (person.hasField("languagesSpoken"))
			user.setLanguagesSpoken(person.getFieldAsList("languagesSpoken"));
		if (person.hasField("food"))
			user.setFood(person.getFieldAsList("food"));
		if (person.hasField("turnOns"))
			user.setTurnOns(person.getFieldAsList("turnOns"));
		if (person.hasField("turnOffs"))
			user.setTurnOffs(person.getFieldAsList("turnOffs"));
		
		if (person.hasField("bodyType"))
		{
			BodyType bodyType = new BodyType();
			Map o = person.getFieldAsMap("bodyType");
			
			if (o.containsKey("build"))
				bodyType.setBuild(o.get("build").toString());
			if (o.containsKey("eyeColor"))
				bodyType.setEyeColor(o.get("eyeColor").toString());
			if (o.containsKey("hairColor"))
				bodyType.setHairColor(o.get("hairColor").toString());
			if (o.containsKey("height"))
				bodyType.setHeight(Double.parseDouble(o.get("height").toString()));
			if (o.containsKey("weight"))
				bodyType.setWeight(Double.parseDouble(o.get("weight").toString()));
			
			user.setBodyType(bodyType);
		}
		
		if (person.hasField("profileSong"))
		{
			Map map = person.getFieldAsMap("profileSong");
			Url url = new Url();
			
			if (map.containsValue("linkText"))
				url.setLinkText(map.get("linkText").toString());
			user.setProfileSong(url);
		}
		
		if (person.hasField("name"))
		{
			Map<String, String> o =  person.getFieldAsMap("name");
			PersonName name = new PersonName();
			
			if (o.containsKey("unstructured"))
				name.setUnstructured(o.get("unstructured"));
			if (o.containsKey("givenName"))
				name.setGivenName(o.get("givenName"));
			if (o.containsKey("familyName"))
				name.setFamilyName(o.get("familyName"));
			
			user.setPname(name);
		}
		
		if (person.hasField("currentLocation"))
		{
			Map<String, String> o = person.getFieldAsMap("currentLocation");
			
			Address address = new Address();
			
			if (o.containsKey("region"))
				address.setRegion(o.get("region"));
			if (o.containsKey("postalCode"))
				address.setPostalCode(o.get("postalCode"));
			if (o.containsKey("country"))
				address.setCountry(o.get("country"));
			if (o.containsKey("latitude"))
				address.setLatitude(Long.parseLong(o.get("latitude")));
			if (o.containsKey("longitude"))
				address.setLongitude(Long.parseLong(o.get("longitude")));
			
			user.setCurrentLocation(address);
		}
		user.setUrls(person.getFieldAsList("urls"));
		user.setJobs(person.getFieldAsList("jobs"));
		
		return user;
	}
	
	public ArrayList<User> fetchFriends(String socialNetworkId, boolean detailed, int level)
	{
		ArrayList<User> friends = new ArrayList<User>();
		List<Person> list = getFriends(socialNetworkId);

		if (list != null)
		{
			for (Person person : list)
			{
				try
				{
					User friend = null;

					if (detailed)
						friend = fetchPerson(person.getId());
					else
						friend = parseToUser(person);

					if (friend != null)
					{
						friend.setFriendshipInfo(new FriendshipInfo(null, socialNetworkId, null, level));
						friends.add(friend);
					}
				}
				catch (Exception e)
				{
					e.printStackTrace();
				}
			}
		}

		return friends;
	}

	private List<Person> getFriends(String socialNetworkId)
	{
		List<Person> list = null;
		
		try 
		{
			if (socialNetworkId != null && !socialNetworkId.isEmpty())
			{
				Request request = PeopleService.getFriends(socialNetworkId);
				Response response = socialClient.send(request);
				list = response.getEntries();
			}
		}
		catch (RequestException e)
		{
		}
		catch (IOException e)
		{
		}
		catch (NullPointerException e)
		{
			/* Isto � um workaround para um erro de parser n�o tratado pela API do opensocial.
			 * Provavelmente o socialNetworkId passado para o servidor est� errado ou n�o existe.
			 * Isso faz com que o Client.send() falhe.
			*/
		}
		return list;
	}
	
	private String extractFromMap(Map map, String field)
	{
		return map.containsKey(field) ? map.get(field).toString() : null;
	}
	
/*	private ArrayList<String> createList(Person openSocialPerson, String strParameter)
	{
		ArrayList<String> list = new ArrayList<String>();
		
		if (openSocialPerson.hasField(strParameter))
		{	
			for (String o : openSocialPerson.getField(strParameter).getStringValues())
				list.add(o);
		}
		return list;
	}
	
	private ArrayList<Url> createUrlList(Person openSocialPerson, String strParameter) throws OpenSocialException
	{
		ArrayList<Url> list = new ArrayList<Url>();
		
		if (openSocialPerson.hasField(strParameter))
		{	
			for (OpenSocialObject o : openSocialPerson.getField(strParameter).getValues())
			{
				Url url = new Url();
				
				if (o.hasField("address"))
					url.setAddress(o.getField("address").getStringValue());
				if (o.hasField("linkText"))
					url.setLinkText(o.getField("linkText").getStringValue());
				if (o.hasField("type"))
					url.setType(o.getField("type").getStringValue());
				
				list.add(url);
			}
		}
		return list;
	}
	
	private ArrayList<Organization> createJobsList(OpenSocialPerson openSocialPerson, String strParameter) throws OpenSocialException
	{
		ArrayList<Organization> list = new ArrayList<Organization>();
		
		if (openSocialPerson.hasField(strParameter))
		{	
			for (OpenSocialObject o : openSocialPerson.getField(strParameter).getValues())
			{
				Organization organization = new Organization();
				
				if (o.hasField("name"))
					organization.setName(o.getField("name").getStringValue());
				if (o.hasField("title"))
					organization.setTitle(o.getField("title").getStringValue());
				
				list.add(organization);
			}
		}
		return list;
	}
*/	
}
